package com.atguigu.zk;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

/*
    通过代码操作Zookeeper
    1.创建客户端对象
    2.具体操作
    3.关闭资源
 */
public class ZKDemo {
    private  ZooKeeper zk;
    /*
        在单元测试方法执行前执行
     */
    @Before
    public void before() throws IOException {
        //1.创建Zookeeper对象
        /*
            ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
            connectString : zookeeper服务器地址
            sessionTimeout : 会话超时时间一般为2倍心跳时间-4000毫秒
            watcher : 监听器对象（一旦事件响应后就会调用此对象中的process方法，process方法中用来处理事件响应后的业务逻辑代码）
hadoop102:2181,hadoop103:2181,hadoop104:2181
         */
        String connectString = "hadoop102:2181";
        zk = new ZooKeeper(connectString, 4000, new Watcher() {
            //当服务器反馈事件信息时就会调用此方法
            public void process(WatchedEvent event) {
                //在该方法中处理事件响应后需要处理的业务逻辑代码
            }
        });
    }
    /*
        在单元测试方法执行后执行
     */
    @After
    public void after(){
        //3.关闭资源
        if (zk != null){
            try {
                zk.close();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /*
        创建子节点
     */
    @Test
    public void test() throws KeeperException, InterruptedException {
        /*
        create(final String path, byte data[], List<ACL> acl,CreateMode createMode)
        path : 节点的路径
        data : 节点中存放的数据
        acl : 访问控制权限
        createMode ： 节点的类型
         */
        zk.create("/xiyouji/aaa","aaaaaaa".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
    }
    /*
     判断节点是否存在
     */
    @Test
    public void test2() throws KeeperException, InterruptedException {
        /*
            exists(String path, boolean watch)
            path : 是节点的路径
            watch : 是否使用总监听器的对象

            返回值 ：如果节点不存在则返回null
         */
        Stat exists = zk.exists("/xiyouji2", false);
        System.out.println(exists==null? "不存在" : "存在");
    }

    /*
        获取子节点并监听节点变化
     */
    @Test
    public void test3() throws KeeperException, InterruptedException {
        /*
        getChildren(final String path, Watcher watcher)
        path : 节点的路径
        watcher ：  监听器对象（一旦事件响应后就会调用此对象中的process方法，process方法中用来处理事件响应后的业务逻辑代码）
         */
        List<String> children = zk.getChildren("/xiyouji", new Watcher() {
            //用来处理事件响应后的业务逻辑代码 --- 监听节点的变化
            public void process(WatchedEvent event) {
                System.out.println("节点发生改变了.......");
            }
        });
        //节点的遍历
        for (String child : children) {
            System.out.println(child);
        }
        //主线程不能死--一直睡
        Thread.sleep(Long.MAX_VALUE);
    }

    @Test
    public void test4() throws Exception {
        listener();
        //主线程不能死--一直睡
        Thread.sleep(Long.MAX_VALUE);
    }
    public void listener() throws KeeperException, InterruptedException {
        List<String> children = zk.getChildren("/sanguo", new Watcher() {
            //用来处理事件响应后的业务逻辑代码 --- 监听节点的变化
            public void process(WatchedEvent event) {
                System.out.println("节点发生改变了.......");
                System.out.println("==========================================");
                try {
                    //再次监听
                    listener();
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //节点的遍历
        for (String child : children) {
            System.out.println(child);
        }
    }
}
